/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Graph;

import java.util.List;
import java.util.ArrayList;

/**
 *
 * @author oliviersputael
 */
public class Graph {
	public Graph(List<Node> V, List<Edges> E) {
		nodes = V;
		edges = E;
	}
	
	public Graph(Graph g) {
		nodes = new ArrayList<Node>(g.getNodes());
		edges = new ArrayList<Edges>(g.getEdges());
		colors = new ArrayList<Color>(g.getColors());
	}
	
	public Graph () {
		nodes = new ArrayList<Node>();
		edges = new ArrayList<Edges>();
		colors = new ArrayList<Color>();
	}
	
	public List<Node> getNodes () {
		return nodes;
	}
	
	public List<Edges> getEdges () {
		return edges;
	}
	
	public List<Color> getColors () {
		return colors;
	}
	
	public Node getNodeFromID (int id) {
		return nodes.get(id);
	}
	
	public Node getNodeFromInstruction (Instructions i) {
		Node result = null;
		
		for (int j = 0; j < nodes.size() && result == null; j++) {
			if (nodes.get(j).getInstruction().equals(i)) {
				result = nodes.get(j);
			}
		}
		
		return result;
	}
	
	public Edges getEdgesFromID (int id) {
		return edges.get(id);
	}
	
	public List<Edges> getUniqueEdgesFromNode (Node n) {
		List<Edges> ed = new ArrayList<Edges>();
		
		for (Edges e : edges) {
			if (e.getNode1().equals(n))
				ed.add(e);
		}
		
		return ed;
	}
	
	public Color getColorFromConstraintNb (int nb) {
		Color result = null;
		boolean found = false;
		
		for (int i = 0; i < colors.size() && !found; i++) {
			if (colors.get(i).getConstraintNb() == nb) {
				found = true;
				result = colors.get(i);
			}
		}
		
		return result;
	}
	
	public int getNumberOfNodes () {
		return nodes.size();
	}
	
	public int getNumberOfEdges () {
		return edges.size();
	}
	
	public boolean addNodeToGraph (Node n) {
		return nodes.add(n);
	}
	
	public void addNodeListToGraph (List<Node> nodeList) {
		for (Node n : nodeList)
			nodes.add(n);
	}
	
	public void colorGraph (Graph MCS) {
		for (Node n : nodes) {
			if (n.isConstrained())
				colorNode(n, getColorFromConstraintNb(n.getConstraint()));
			else {
				for (Node sameNodes : MCS.getNodes()) {
					if (n.equals(sameNodes))
						n.setColor(sameNodes.getColor());
				}
			}
		}
	}
	
	public void colorNode (Node n, Color c) {
		if (!n.isColored()) {
			n.setColor(c);
			for (Edges e : edges) {
				if (e.contains(n)) 
					colorNode(e.getOtherNode(n), c);
			}
		}
	}
	
	public void addColorListToGraph (List<Color> colorList) {
		for (Color c : colorList)
			colors.add(c);
	}
	
	public void removeNodeFromGraph (Node n) {
		List<Edges> copy = new ArrayList<Edges>(edges);
		
		for (Edges e : copy) {
			if (e.contains(n)) {
				removeEdgeFromGraph(e);
				removeNodeFromGraph(e.getOtherNode(n));
			}
		}
		
		/*
		 * OLD VERSION
		 * for (Node connections : n.getConnections()) {
			removeEdgeFromGraph(new Edges(n, connections, 0));
			removeNodeFromGraph(connections);
		}*/
		
		nodes.remove(n);
	}
	
	public boolean addEdgeToGraph (Edges e) {
		return edges.add(e);
	}
	
	public void removeEdgeFromGraph (Edges e) {
		edges.remove(e);
		/*
		 * OLD VERSION
		 * boolean found = false;
		for (int i = 0; i < edges.size() && !found; i++) {
			if (edges.get(i).equals(e)) {
				edges.remove(i);
				found = true;
			}
		}*/
	}
	
	public boolean isAnEdge(Node n1, Node n2) {
		boolean found = false;
		
		for (int i = 0; i < edges.size() && !found; i++) {
			found = (  edges.get(i).getNode1().equals(n1) && edges.get(i).getNode2().equals(n2) 
					|| edges.get(i).getNode1().equals(n2) && edges.get(i).getNode2().equals(n1));
		}
		
		return found;
	}
	
	public Edges getEdgeFromNodes (Node n1, Node n2) {
		Edges e = null;
		
		for (int i = 0; i < edges.size() && e == null; i++) {
			if (edges.get(i).getNode1().equals(n1) && edges.get(i).getNode2().equals(n2)
				|| edges.get(i).getNode1().equals(n2) && edges.get(i).getNode2().equals(n1))
				e = new Edges(edges.get(i));
		}
		
		return e;
	}
	
	public void generateEdges () {
		for (Node n1 : nodes) {
			for (Node n2 : nodes) {
				if (!n1.equals(n2) && !isAnEdge(n1, n2)){ // self edge not permitted
					if (n1.mustBeLinkedTo(n2)) {
							addEdgeToGraph(new Edges(n1, n2, 1));
					}
				} 
			}
		}
	}
	
	@Override
	public String toString () {
		/*String toString = "";
		
		toString = toString + "===========================\n";
		toString = toString + "Graph : \n";
		for (Node n : nodes) {
			toString = toString + "  > ";
			toString = toString + n.toString();
			toString = toString + "------------------------------\n";
		}
		for (Edges e : edges) {
			toString = toString + "  > ";
			toString = toString + e.toString();
			toString = toString + "------------------------------\n";
		}
		toString = toString + "===========================";
		*/
		
		// DEBUG ONLY
		String toString = "";
		
		for (Node n : nodes) {
			toString = toString + n.getColor().getName().substring(0, 1);
		}
		toString = toString + "\n";
		
		return toString;
	}
	
	private List<Node> nodes;
	private List<Edges> edges;
	private List<Color> colors;
}
